package com.lzs.bootsafety.common.util.oss;

import com.alibaba.fastjson.JSON;
import com.lzs.bootsafety.common.oss.Exception.OssException;
import com.lzs.bootsafety.common.util.SevletUtils;
import com.lzs.bootsafety.common.util.enums.FileType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;

public class FileUtils {

    /**
     * 获取文件后缀
     * @param fileName
     * @return
     */
    public static String getSuffix(String fileName) {
        int index = fileName.lastIndexOf(".");
        index = -1 == index ? fileName.length() : index;
        return fileName.substring(index);
    }
    public static String getSuffix(File file){
        return getSuffix(file.getName());
    }

    public  static String generateTempFileName(String fileUrl){
        return getSuffixByUrl(fileUrl);
    }
    public static String getSuffixByUrl(String fileUrl){
        String defaultSuffix=".png";
        if (StringUtils.isEmpty(fileUrl)){
            return defaultSuffix;
        }
        String fileName = fileUrl;
        if (fileUrl.contains("/")){
            fileName=fileUrl.substring(fileUrl.lastIndexOf("/"));
        }
        String fileSuffix = getSuffix(fileName);
        return StringUtils.isEmpty(fileSuffix) ? defaultSuffix : fileSuffix;
    }
    /**---------------获取魔数值-----------------*/
    /** 读取文件头 */
    private static String getFileHeader(InputStream inputStream) throws IOException {
        byte[] b = new byte[28];
        try {
            inputStream.read(b, 0, 28);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
        return bytesToHex(b);
    }
    /** 将字节数组转换成16进制字符串 */
    public static String bytesToHex(byte[] src){
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            /**保持二进制补码的一致性 因为byte类型字符是8bit的  而int为32bit 会自动补齐高位1
            所以与上0xFF之后可以保持高位一致性 当byte要转化为int的时候，高的24位必然会补1，这样，其二进制补码其实已经不一致了，
            & 0xff可以将高的24位置为0，低8位保持原样，这样做的目的就是为了保证二进制数据的一致性。*/
            int v = src[i] & 0xFF;//0x 代表16进制   每一位取值范围是  0 —— 15 但是 10——15之间是两位数字了，会和10进制分部开 所以 10——15就对应了 A——F
            String hv = Integer.toHexString(v);//将整数转为16进制
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }
    /** 判断文件类型  */
    public static FileType getType(InputStream inputStream) throws IOException {
        // 获取文件头
        String fileHead = getFileHeader(inputStream);
        if (fileHead != null && fileHead.length() > 0) {
            fileHead = fileHead.toUpperCase();
            FileType[] fileTypes = FileType.values();
            for (FileType type : fileTypes) {
                if (fileHead.startsWith(type.getValue())) {
                    return type;
                }
            }
        }
        return null;
    }
    /**
     * 复制InputStream
     *
     * @param is InputStream
     * @return
     */
    public static InputStream clone(InputStream is) {
        if(null == is){
            throw new OssException("无法获取文件流，文件不可用！");
        }
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = is.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return new ByteArrayInputStream(baos.toByteArray());
        } catch (IOException e) {
            throw new OssException("无法复制当前文件流！", e);
        }
    }
    public static final byte[] StreamToByte(InputStream inStream)throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        return in2b;
    }
    /**  */
    public static void downloadFile(String fileName, InputStream is,String storageType){
        HttpServletResponse response = SevletUtils.getResponse();
        String userAgent = SevletUtils.getRequest().getHeader("User-Agent");
        OutputStream out = null;
        String filename;
        try {
            if(userAgent.contains("MSIE") || userAgent.contains("Trident")) {//ie防止中文乱码
                filename = java.net.URLEncoder.encode(fileName, "UTF-8");
            }else {
                filename = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
            }
            response.setContentType("multipart/form-data");
            response.setCharacterEncoding("utf-8");
            response.setHeader("Content-Disposition", String.format("attachment; filename=\"%s\"", filename));//设置Content-Disposition
            response.setHeader("filename", filename);
            out = response.getOutputStream();
            byte[] bytes = new byte[1024];
            int len;//在外部定义len,然后每次len(为的是最后一次的细节长度)都等于流往数组中存放的长度
            while ((len = is.read(bytes)) != -1) {//值是0-255如果返回-1就说明没值了
                out.write(bytes,0,len);//使用write(byte[] bytes,int off,int len);不会改变文件内容长度
            }
            out.flush();
            out.close();
            is.close();
        } catch (IOException e) {
            try {
                response.reset();
                response.setContentType("application/json");
                response.setCharacterEncoding("utf-8");
                Map<String, String> map = new HashMap<String, String>();
                map.put("status", "failure");
                map.put("message", "下载文件失败" + e.getMessage());
                response.getWriter().println(JSON.toJSONString(map));
            } catch (IOException e1) {
                throw new OssException("[" + storageType + "]文件下载失败："+e.getMessage());
            }
        }

    }



}
